import React, { useEffect, useRef, useState } from "react";
import { Graph, Platform, StringExt, Cell, Node, Edge } from "@antv/x6";
import { Selection } from "@antv/x6-plugin-selection";
import { History } from "@antv/x6-plugin-history";
import { MiniMap } from "@antv/x6-plugin-minimap";
import { Button, Col, message, Row, Space } from "antd";
import {
  UndoOutlined,
  RedoOutlined,
  ZoomInOutlined,
  ZoomOutOutlined,
} from "@ant-design/icons";
import { initGraphConfig } from "./GraphConfig";
import { NodeType } from "./types";
import { getPortsByType } from "./utils";
import { DynamicNode } from "hqhui";
import NodeTypeSelector from "./NodeTypeSelector";
import { initInjectDynamicNode } from "../../example";
import { Snapline } from "@antv/x6-plugin-snapline";
import { Keyboard } from "@antv/x6-plugin-keyboard";

/**
 * @file index.tsx
 * @description 数据处理流程图主组件，用于创建、展示和编辑数据处理流程
 */

// 初始化图表配置
initGraphConfig();

/**
 * 流程图组件
 * 提供完整的流程图编辑功能，包括节点添加、连接、编辑、撤销/重做等
 */
const DifyFlowEditor: React.FC = () => {
  // 容器引用
  const containerRef = useRef<HTMLDivElement>(null);
  // 图表实例引用
  const graphRef = useRef<Graph | null>(null);
  // 小地图容器引用
  const miniMapRef = useRef<HTMLDivElement>(null);
  // 当前选中的节点类型
  const [selectNodeType, setSelectNodeType] = useState<NodeType | null>(null);
  // 当前选中的节点id
  const [selectNodeId, setSelectNodeId] = useState<string | null>(null);
  // 节点类型菜单是否显示
  const [showNodeTypeMenu, setShowNodeTypeMenu] = useState(false);
  // 菜单位置
  const [menuPosition, setMenuPosition] = useState({ x: 0, y: 0 });
  // 菜单上下文信息
  const [menuContext, setMenuContext] = useState<{
    source: Cell | null;
    target: Cell | null;
    edge: Cell | null;
  }>({ source: null, target: null, edge: null });
  // 历史记录状态
  const [historyState, setHistoryState] = useState({
    canUndo: false,
    canRedo: false,
  });

  useEffect(() => {
    if (!containerRef.current) return;
    // 创建图表实例
    const graph: Graph = new Graph({
      container: containerRef.current,
      autoResize: true,
      panning: true, // 画布平移
      grid: true, // 网格大小 10px，并绘制网格
      // 画布缩放
      mousewheel: {
        enabled: true,
        modifiers: ["ctrl", "meta"],
      },
      // 连线选项
      connecting: {
        snap: true, // 是否开启自动吸附
        allowBlank: false, // 是否允许连接到画布空白位置的点
        allowLoop: false, //  是否允许创建循环连线，即边的起始节点和终止节点为同一节点
        highlight: true, // 拖动边时，是否高亮显示所有可用的连接桩或节点，默认值为 false
        // 指定源节点的锚点
        sourceAnchor: {
          name: "left",
          args: {
            dx: Platform.IS_SAFARI ? 4 : 8,
          },
        },
        // 指定目标节点的锚点
        targetAnchor: {
          name: "right",
          args: {
            dx: Platform.IS_SAFARI ? 4 : -8,
          },
        },
        // 自定义新建的边的样式
        createEdge() {
          return graph.createEdge({
            shape: "data-processing-curve",
            attrs: {
              line: {},
            },
            zIndex: -1,
          });
        },
        // 连接桩校验
        validateConnection({ sourceMagnet, targetMagnet }) {
          // 只能从输出连接桩创建连接
          if (
            !sourceMagnet ||
            sourceMagnet.getAttribute("port-group") === "in"
          ) {
            return false;
          }
          // 只能连接到输入连接桩
          if (
            !targetMagnet ||
            targetMagnet.getAttribute("port-group") !== "in"
          ) {
            return false;
          }
          return true;
        },
      },
      // 高亮选项
      highlighting: {
        magnetAdsorbed: {
          name: "stroke",
          args: {
            attrs: {
              fill: "#fff",
              stroke: "#2563eb",
              strokeWidth: 4,
            },
          },
        },
      },
    });

    // 使用选择插件
    graph
      .use(
        new Selection({
          multiple: false,
          rubberband: true, // 允许框选
          // showNodeSelectionBox: true, // 显示节点选中框
        })
      )
      .use(new Snapline()) // 启用对齐参考线
      .use(new Keyboard()) // 启用键盘快捷键
      .use(new History()); // 启用历史记录（撤销/重做）
    if (miniMapRef.current) {
      // 使用小地图插件
      graph.use(
        new MiniMap({
          container: miniMapRef.current,
          width: 200,
          height: 160,
          padding: 10,
        })
      );
    }
    //  删除（Backspace键）
    graph.bindKey("backspace", () => {
      const cells = graph.getSelectedCells(); // 获取选中的元素
      if (cells.length) {
        graph.removeCells(cells); // 删除选中元素
      }
    });
    // 节点选中事件处理
    graph.on("node:selected", ({ node }: any) => {
      setSelectNodeId(node.id);
      setSelectNodeType(node.data.value);
    });
    // 节点hover - 修改关联边的颜色
    graph.on("node:mouseenter", ({ node }: any) => {
      // 获取与当前节点相连的所有边
      const edges = graph.getEdges().filter((edge) => {
        const source = edge.getSourceCellId();
        const target = edge.getTargetCellId();
        return source === node.id || target === node.id;
      });

      // 修改关联边的颜色为高亮色
      edges.forEach((edge) => {
        // 存储原始颜色，以便恢复
        edge.setData({
          ...edge.getData(),
          originalStrokeColor: edge.attr("line/stroke"),
        });
        // 设置高亮颜色（蓝色）
        edge.setAttrByPath("line/stroke", "#2563eb");
      });
    });

    // 鼠标离开节点 - 恢复关联边的原始颜色
    graph.on("node:mouseleave", ({ node }: any) => {
      // 获取与当前节点相连的所有边
      const edges = graph.getEdges().filter((edge) => {
        const source = edge.getSourceCellId();
        const target = edge.getTargetCellId();
        return source === node.id || target === node.id;
      });

      // 恢复关联边的原始颜色
      edges.forEach((edge) => {
        const originalColor = edge.getData().originalStrokeColor || "#A2B1C3";
        edge.setAttrByPath("line/stroke", originalColor);

        // 清除临时存储的原始颜色
        const data = edge.getData();
        delete data.originalStrokeColor;
        edge.setData(data);
      });
    });

    // 边鼠标悬停事件处理
    graph.on("edge:mouseenter", ({ cell }) => {
      cell.addTools([
        {
          name: "button",
          args: {
            markup: [
              {
                tagName: "circle",
                selector: "button",
                attrs: {
                  r: 8,
                  stroke: "#2563eb",
                  strokeWidth: 1,
                  fill: "white",
                  cursor: "pointer",
                },
              },
              {
                tagName: "text",
                textContent: "+",
                selector: "icon",
                attrs: {
                  fill: "#2563eb",
                  fontSize: 12,
                  textAnchor: "middle",
                  pointerEvents: "none",
                  y: "0.3em",
                },
              },
            ],
            distance: "50%",
            onClick({ view, e }: any) {
              graph.cleanSelection();
              const edge = view.cell as Edge;
              const source = edge.getSourceCell() as Cell;
              const target = edge.getTargetCell() as Cell;

              if (source && target) {
                setMenuPosition({
                  x: e.clientX + 20,
                  y: e.clientY - 10,
                });

                setMenuContext({
                  source,
                  target,
                  edge,
                });

                setShowNodeTypeMenu(true);
              }
            },
          },
        },
      ]);
    });

    // 边鼠标离开事件处理
    graph.on("edge:mouseleave", ({ cell }) => {
      if (cell.hasTool("button")) {
        cell.removeTool("button");
      }
    });

    // 边选中事件 - 修改边的颜色
    graph.on("edge:selected", ({ cell }) => {
      // 修改边的线条颜色为蓝色（可根据需求调整）
      cell.setAttrByPath("line/stroke", "#2563eb");
    });

    // 边取消选中事件 - 恢复边的原始颜色
    graph.on("edge:unselected", ({ cell }) => {
      // 恢复边的原始线条颜色
      cell.setAttrByPath("line/stroke", "#A2B1C3");
    });

    graphRef.current = graph;

    /**
     * 加载示例数据
     * 在实际应用中替换为真实的数据源
     */
    const loadExampleData = async () => {
      try {
        const exampleData = {
          nodes: [
            {
              id: "node-0",
              shape: "custom-node",
              x: 100,
              y: 100,
              ports: getPortsByType(NodeType.INPUT, "node-0"),
              data: { label: "数据输入", value: NodeType.INPUT },
            },
            {
              id: "node-1",
              shape: "custom-node",
              x: 400,
              y: 100,
              ports: getPortsByType(NodeType.FILTER, "node-1"),
              data: { label: "数据筛选", value: NodeType.FILTER },
            },
            {
              id: "node-2",
              shape: "custom-node",
              x: 700,
              y: 100,
              ports: getPortsByType(NodeType.JOIN, "node-2"),
              data: { label: "数据连接", value: NodeType.JOIN },
            },
            {
              id: "node-3",
              shape: "custom-node",
              x: 1000,
              y: 100,
              ports: getPortsByType(NodeType.AGG, "node-3"),
              data: { label: "数据聚合", value: NodeType.AGG },
            },
            {
              id: "node-4",
              shape: "custom-node",
              x: 1300,
              y: 100,
              ports: getPortsByType(NodeType.OUTPUT, "node-4"),
              data: { label: "数据输出", value: NodeType.OUTPUT },
            },
          ],
          edges: [
            {
              id: "edge-0",
              shape: "data-processing-curve",
              source: { cell: "node-0", port: "node-0-out" },
              target: { cell: "node-1", port: "node-1-in" },
              zIndex: -1,
            },
            {
              id: "edge-1",
              shape: "data-processing-curve",
              source: { cell: "node-1", port: "node-1-out" },
              target: { cell: "node-2", port: "node-2-in" },
              zIndex: -1,
            },
            {
              id: "edge-2",
              shape: "data-processing-curve",
              source: { cell: "node-2", port: "node-2-out" },
              target: { cell: "node-3", port: "node-3-in" },
              zIndex: -1,
            },
            {
              id: "edge-3",
              shape: "data-processing-curve",
              source: { cell: "node-3", port: "node-3-out" },
              target: { cell: "node-4", port: "node-4-in" },
              zIndex: -1,
            },
          ],
        };
        graph.fromJSON(exampleData);
        graph.zoomToFit({ padding: { left: 10, right: 10 } });
      } catch (error) {
        console.error("Failed to load graph data:", error);
      }
    };

    // 加载示例数据
    loadExampleData();

    // 添加历史状态变化的事件监听
    graph.on("history:change", () => {
      if (graphRef.current) {
        const history = graphRef.current.getPlugin<History>("history");
        if (history) {
          setHistoryState({
            canUndo: history.canUndo(),
            canRedo: history.canRedo(),
          });
        }
      }
    });

    // 清理函数
    return () => {
      graph.dispose();
    };
  }, []);

  /**
   * 撤销操作
   */
  const handleUndo = () => {
    if (graphRef.current) {
      const history = graphRef.current.getPlugin<History>("history");
      if (history && history.canUndo()) {
        history.undo();
      }
    }
  };

  /**
   * 恢复操作
   */
  const handleRedo = () => {
    if (graphRef.current) {
      const history = graphRef.current.getPlugin<History>("history");
      if (history && history.canRedo()) {
        history.redo();
      }
    }
  };

  /**
   * 放大操作
   */
  const handleZoomIn = () => {
    if (graphRef.current) {
      const currentZoom = graphRef.current.zoom();
      const newZoom = Math.min(currentZoom * 1.1, 1.5); // 最大放大到1.5倍
      graphRef.current.zoomTo(newZoom);
    }
  };

  /**
   * 缩小操作
   */
  const handleZoomOut = () => {
    if (graphRef.current) {
      const currentZoom = graphRef.current.zoom();
      const newZoom = Math.max(currentZoom / 1.1, 0.5); // 最小缩小到0.5倍
      graphRef.current.zoomTo(newZoom);
    }
  };

  /**
   * 处理节点类型选择
   * @param nodeType 选中的节点类型
   */
  const handleNodeTypeSelect = (nodeType: NodeType) => {
    const { source, target, edge } = menuContext;
    if (source && target && edge) {
      // 获取边的中间位置作为新节点的位置
      const sourcePos = (source as Node).getPosition();
      const targetPos = (target as Node).getPosition();
      const middlePos = {
        x: (sourcePos.x + targetPos.x) / 2,
        y: (sourcePos.y + targetPos.y) / 2,
      };

      // 创建新节点
      const newNodeId = StringExt.uuid();
      const newNode = graphRef.current?.addNode({
        id: newNodeId,
        shape: "custom-node",
        x: middlePos.x,
        y: middlePos.y,
        ports: getPortsByType(nodeType, newNodeId),
        data: {
          label: `新节点-${nodeType}`,
          value: nodeType,
        },
      });

      // 删除原来的边
      graphRef.current?.removeCell(edge);

      // 创建从源节点到新节点的边
      if (newNode) {
        graphRef.current?.addEdge({
          id: StringExt.uuid(),
          shape: "data-processing-curve",
          source: { cell: source.id, port: `${source.id}-out` },
          target: { cell: newNode.id, port: `${newNode.id}-in` },
          zIndex: -1,
        });

        // 创建从新节点到目标节点的边
        graphRef.current?.addEdge({
          id: StringExt.uuid(),
          shape: "data-processing-curve",
          source: { cell: newNode.id, port: `${newNode.id}-out` },
          target: { cell: target.id, port: `${target.id}-in` },
          zIndex: -1,
        });
      }

      // 选择新创建的节点，展示配置面板
      if (newNode) {
        graphRef.current?.select(newNode as Cell);
        setSelectNodeType(nodeType);
      }
    }

    // 隐藏菜单
    setShowNodeTypeMenu(false);
  };

  /**
   * 保存
   */
  const handleSave = () => {
    if (graphRef.current) {
      const nodeData = graphRef.current.getNodes();
      const edgeData = graphRef.current.getEdges();
      const cellData = graphRef.current.getCells();
      console.log("所有节点数据"+JSON.stringify(nodeData));
      console.log("所有边数据"+JSON.stringify(edgeData));
      console.log("所有边&&节点数据"+JSON.stringify(cellData));
      message.success('保存成功')
    }
  };
  /**
   * 节点配置项数据
   * @param data 
   */
  const handleNodeConfigData = (data:any) => {
    console.log("节点id:" + selectNodeId)
    const  node = graphRef.current?.getCellById(selectNodeId as string)
    node?.setData({
      ...node?.data,
      configData: data
    })
    console.log("节点配置项数据:"+ JSON.stringify(data))
  }

  return (
    <div className="p-4 flex flex-col min-h-screen w-full">
      <div className="header mb-2 w-full">
        <h2 className="text-xl font-bold mb-2">流程编排DEMO</h2>
        <Row>
          <Col span={18}>
            {/* 工具栏 */}
            <Space>
              <Button
                icon={<UndoOutlined />}
                onClick={handleUndo}
                disabled={!historyState.canUndo}
                size="small"
              >
                撤销
              </Button>
              <Button
                icon={<RedoOutlined />}
                onClick={handleRedo}
                disabled={!historyState.canRedo}
                size="small"
              >
                恢复
              </Button>
              <Button
                icon={<ZoomInOutlined />}
                onClick={handleZoomIn}
                size="small"
              >
                放大
              </Button>
              <Button
                icon={<ZoomOutOutlined />}
                onClick={handleZoomOut}
                size="small"
              >
                缩小
              </Button>
            </Space>
          </Col>
          <Col offset={1} span={5}>
            <Space>
              <Button
                type="primary"
                ghost
                size="small"
                onClick={initInjectDynamicNode}
              >
                注入动态节点
              </Button>
              <Button
                type="primary"
                size="small"
                onClick={handleSave}
              >
                保存
              </Button>
            </Space>
          </Col>
        </Row>
      </div>
      <div className="content w-full flex justify-between items-center relative">
        <div
          ref={containerRef}
          className="border border-gray-200 rounded-md bg-gray-50 h-[550px] flex-1 relative"
        />
        <div className="configForm w-[300px] h-[550px] border ml-2">
          {
            selectNodeType && 
            <DynamicNode 
             nodeType={selectNodeType} 
             callValidateData={handleNodeConfigData}
            />
          }
        </div>
        <div
          id="miniMapContainer"
          ref={miniMapRef}
          className="absolute bottom-2 left-10"
        ></div>

        {/* 节点类型选择下拉菜单 */}
        <NodeTypeSelector
          visible={showNodeTypeMenu}
          position={menuPosition}
          context={menuContext}
          onNodeTypeSelect={handleNodeTypeSelect}
          onClose={() => setShowNodeTypeMenu(false)}
        />
      </div>
    </div>
  );
};

export default DifyFlowEditor;
